package com.nintendo.zk;

import com.nintendo.pojo.netty.NettyServerNode;
import com.nintendo.utils.JedisPoolUtil;
import com.nintendo.utils.JsonUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;

@Slf4j
@Component
@ConfigurationProperties(prefix = "zookeeper.curator")
@Data
public class CuratorConfig {
    private String host;// zookeeper地址
    private Integer connectionTimeoutMs;//连接超时时间
    private Integer sessionTimeoutMs;//会话超时时间
    private Integer sleepMsBetweenRetry;// 休眠时间
    private Integer maxRetries; // 最大重试次数
    private String namespace; // 命名空间
    public static final String PATH = "/server-list";

    @Resource
    private RabbitAdmin rabbitAdmin;
    @Bean("curatorClient")
    public CuratorFramework curatorClient() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(sleepMsBetweenRetry, maxRetries);
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(host)
                .sessionTimeoutMs(sessionTimeoutMs)
                .connectionTimeoutMs(connectionTimeoutMs)
                .retryPolicy(retryPolicy)
                .namespace(namespace)
                .build();
        client.start();
        log.info("zookeeper连接成功");
//        try {
//            client.create().creatingParentContainersIfNeeded().forPath("/springboot/test","spingcloud".getBytes());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        // 注册监听watcher事件
        addWatcher(PATH, client);
        return client;
    }

    /**
     * 注册节点的事件监听
     *
     * @param path
     * @param client
     */
    public void addWatcher(String path, CuratorFramework client) {
        Jedis jedis = JedisPoolUtil.getJedis();
        CuratorCache curatorCache = CuratorCache.build(client, path);
        curatorCache.listenable().addListener((type, oldData, newData) -> {
            // type 当前监听到的事件类型
            // oldData 节点更新前的数据包括状态
            // newData 节点更新后的数据和状态
            System.out.println(type);
//            if (newData != null) {
//                System.out.println("new path = " + String.valueOf(newData.getPath()));
//                System.out.println("new value = " + String.valueOf(newData.getData()));
//            }
//            if (oldData != null) {
//                System.out.println("old path = " + String.valueOf(oldData.getPath()));
//                System.out.println("old data = " + String.valueOf(oldData.getData()));
//            }
            switch (type.name()) {
                case "NODE_CREATED":
                    log.info("(子)节点创建成功");
                    break;
                case "NODE_CHANGED":
                    log.info("(子)节点数据变更");
                    break;
                case "NODE_DELETED":
                    log.info("(子)节点删除");
                    NettyServerNode oldNode = JsonUtils.jsonToPojo(new String(oldData.getData()),NettyServerNode.class);
                    log.info("节点数据：{}", oldNode);
                    String oldPort = oldNode.getPort()+"";
                    String portKey = "netty_port";
                    String endKey = portKey+":"+oldPort;
                    log.info("endKey:{}",endKey);
                    jedis.hdel(portKey,oldPort);
                    String queueName = "netty_queue_"+oldPort;
                    rabbitAdmin.deleteQueue(queueName);
                    break;
                default:
                    log.info("其他事件");
                    break;
            }
        });
        curatorCache.start();
    }
}
